import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js';
import Sizes from './Sizes';
import Camera from './Camera'
import Renderer from './Renderer';
import Time from './Time';
import Cube from './Cube';
import Utils from './Utils';
import Group from './Group';
import Box3 from './Box3';
import Light from './Light';
import CssRender from './CssRender';
import CreateModel from '../shape/Model'
import Assets from './Assets';
import assets from '../data/assets'

import Data from '../data/index'
// 单例 由于THREE.js中各种类互有引用 因此创建一个统一的类来管理它们
export default class Experience {
    static instance;
    constructor(canvas, outBox) {

        if (Experience.instance) return Experience.instance;
        Experience.instance = this;

        // 加载资源加载器
        this.textureLoader = new THREE.TextureLoader();
        this.fileLoader = new THREE.FileLoader();
        this.fileLoader.setResponseType('json');
        this.dracoLoader = new DRACOLoader();
        this.dracoLoader.setDecoderPath('./draco/');
        this.gltfLoader = new GLTFLoader();
        this.gltfLoader.setDRACOLoader(this.dracoLoader)
        this.fontLoader = new FontLoader();

        // 加载资源
        this.assets = new Assets(assets);

        // 加载模拟数据
        this.data = new Data();
        this.outBox = outBox;
        this.canvas = canvas;
        this.scene = new THREE.Scene();
        this.light = new Light();
        this.box3 = new Box3();
        this.sizes = new Sizes();
        this.camera = new Camera();
        this.time = new Time();
        this.renderer = new Renderer();
        this.utils = new Utils();

        this.cssRender = new CssRender();
        // this.cube = new Cube();
        this.group = new Group();
        
        this.model = new CreateModel();

        this.time.on('update', () => {
            this.update();
        })
        this.sizes.on('resize', () => {
            this.resize();
        })
    }
    update() {
        this.camera.update();
        this.renderer.update();
        this.group.update();
        this.cssRender.update();
    }
    resize() {
        this.camera.resize();
        this.renderer.resize();
        this.cssRender.resize();
    }
    destroy() {
        Experience.instance = null;
    }
}